﻿#region Copyright (c) 2008 plexBB Team

/*  Copyright (c) 2008 plexBB Team
 *  
 *  This file is free software: you may copy, redistribute and/or modify it  
 *  under the terms of the GNU General Public License as published by the  
 *  Free Software Foundation, either version 2 of the License, or (at your  
 *  option) any later version.  
 *  
 *  This file is distributed in the hope that it will be useful, but  
 *  WITHOUT ANY WARRANTY; without even the implied warranty of  
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
 *  General Public License for more details.  
 *  
 *  You should have received a copy of the GNU General Public License  
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */

#endregion

using System;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using PlexBB.Data;
using PlexBB.ModuleModel;

namespace PlexBB.Controls.Admin.ModuleManagement
{
    public abstract class AcpModuleEdit : AcpModuleControlBase
    {
        private const string _builtInModulesPrefix = "PlexBB.Templates.";
        private const string _infoSuffix = "Info";
        private Module _editModule;

        #region Controls

        protected IButtonControl bModuleSubmit;
        protected HtmlControl gModOptions;
        protected HyperLink hBack;
        protected ListControl sChooseMode;
        protected ListControl sChooseModule;
        protected ListControl sModuleDisplayed;
        protected ListControl sModuleEnabled;
        protected ListControl sModuleParentID;
        protected ListControl sModuleType;
        protected ITextControl tModuleLangName;
        protected ITextControl tModuleName;

        #endregion

        private int? EditModuleID
        {
            get { return Request.QueryString["eid"] == null ? (int?)null : int.Parse(Request.QueryString["eid"]); }
        }

        private Module EditModule
        {
            get
            {
                if (_editModule == null && EditModuleID.HasValue)
                {
                    _editModule = Data.Modules.SingleOrDefault(m => m.ModuleID == EditModuleID);
                }
                return _editModule;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (!IsPostBack)
            {
                tModuleName.Text = Lang[EditModule.LangName];
                tModuleLangName.Text = EditModule.LangName;
                string selectedValue = EditModule.IsCategory ? "category" : "module";
                sModuleType.SelectedIndex = -1;
                sModuleType.Items.FindByValue(selectedValue).Selected = true;

                // build full categories hierarchy
                ListItem noParentItem = new ListItem(Lang["NO_PARENT"], string.Empty);
                sModuleParentID.Items.Add(noParentItem);
                AddCategoriesToListRecursive(null, sModuleParentID, 0);

                sModuleEnabled.Text = EditModule.Enabled.ToString();
                sModuleDisplayed.Text = EditModule.Display.ToString();

                Type moduleInfoType = typeof(IModuleInfo);

                // select all available modules from all loaded assemblies
                var modules = AppDomain.CurrentDomain.GetAssemblies().Select(assembly =>
                                                                             from type in assembly.GetTypes()
                                                                             where
                                                                                 moduleInfoType.IsAssignableFrom(type) &&
                                                                                 !type.IsInterface &&
                                                                                 !type.IsAbstract &&
                                                                                 type.FullName.EndsWith(_infoSuffix)
                                                                             let name =
                                                                                 type.FullName.StartsWith(
                                                                                     _builtInModulesPrefix)
                                                                                     ? type.FullName.Substring(
                                                                                           _builtInModulesPrefix.Length)
                                                                                     : type.FullName
                                                                             select new
                                                                                        {
                                                                                            Text =
                                                                                 string.Format("{0} [{1}]",
                                                                                               Lang[
                                                                                                   ((IModuleInfo)
                                                                                                    Activator.
                                                                                                        CreateInstance(
                                                                                                        type)).
                                                                                                       LangName],
                                                                                               name.Substring(0,
                                                                                                              name.
                                                                                                                  Length -
                                                                                                              _infoSuffix
                                                                                                                  .
                                                                                                                  Length)),
                                                                                            Value = type.FullName
                                                                                        }).SelectMany(t => t).OrderBy(
                    t => t.Text);

                sChooseModule.DataTextField = "Text";
                sChooseModule.DataValueField = "Value";
                sChooseModule.DataSource = modules;
                sChooseModule.DataBind();
                sChooseModule.Text = EditModule.ModuleType + _infoSuffix;

                SetModuleModes();
                sChooseMode.Text = EditModule.ModuleMode;
                hBack.NavigateUrl = CreateUrl(ParentModuleID, null);
            }
            bModuleSubmit.Click += bModuleSubmit_Click;
            sChooseModule.SelectedIndexChanged += sChooseModule_SelectedIndexChanged;
        }

        private void bModuleSubmit_Click(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                EditModule.LangName = tModuleLangName.Text.Trim();
                EditModule.Enabled = bool.Parse(sModuleEnabled.Text);
                if (sModuleType.SelectedValue == "category")
                {
                    EditModule.ControlType = null;
                    EditModule.ModuleMode = null;
                    EditModule.Display = true;
                }
                else
                {
                    EditModule.ControlType = sChooseModule.Text.Substring(0,
                                                                          sChooseModule.Text.Length - _infoSuffix.Length);
                    EditModule.ModuleMode = sChooseMode.Text;
                    EditModule.Display = bool.Parse(sModuleDisplayed.Text);
                }
                Data.SubmitChanges();

                ShowMessage(null, Lang["MODULE_EDITED"], CreateUrl(ParentModuleID, null), true, true);
            }
        }

        private void sChooseModule_SelectedIndexChanged(object sender, EventArgs e)
        {
            SetModuleModes();
        }

        private void SetModuleModes()
        {
            string moduleInfoType = sChooseModule.SelectedValue;
            var moduleInfo = (IModuleInfo)Activator.CreateInstance(Type.GetType(moduleInfoType));

            sChooseMode.DataSource = from mode in moduleInfo.SupportedModes
                                     let name = Lang[mode.LangName]
                                     orderby name
                                     select new { Text = name, Value = mode.ModeName };
            sChooseMode.DataTextField = "Text";
            sChooseMode.DataValueField = "Value";

            sChooseMode.DataBind();
        }

        private void AddCategoriesToListRecursive(int? parentModuleID, ListControl control, int level)
        {
            var categories = from m in Data.Modules
                             where
                                 m.ModuleMode == CurrentModule.ModuleMode && m.ModuleType == null &&
                                 Equals(m.ParentID, parentModuleID)
                             orderby m.Position
                             select new { m.ModuleID, m.LangName };
            foreach (var cat in categories)
            {
                StringBuilder catName = new StringBuilder();
                const char nonBreakSpace = (char)0xA0;
                for (int i = 0; i < level * 3; i++)
                {
                    catName.Append(nonBreakSpace);
                }
                catName.Append(Lang[cat.LangName]);

                ListItem item = new ListItem(catName.ToString(), cat.ModuleID.ToString());
                control.Items.Add(item);
                AddCategoriesToListRecursive(cat.ModuleID, control, level + 1);
            }
        }
    }
}